﻿using CleanArchitecture.Core.Events;
using CleanArchitecture.Core.Handlers;
using CleanArchitecture.Core.Interfaces;
using CleanArchitecture.Core.Interfaces.Cache;
using CleanArchitecture.Infrastructure.Configuration;
using CleanArchitecture.Infrastructure.Entities;
using CleanArchitecture.Infrastructure.Entities.System.DataDic;
using CleanArchitecture.Infrastructure.Interfaces;
using CleanArchitecture.Infrastructure.Interfaces.SystemManage;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CleanArchitecture.Infrastructure.Services.SystemManage
{
    public class SystemDataDicService : ISystemDataDicService
    {
        private readonly IRepository<SystemDataDicTree> _systemdatadictreeRepository;
        private readonly IRepository<SystemDataDicButton> _systemdatadicbtnRepository;
        private readonly IDomainEventDispatcher _eventDispatcher;
        private readonly IStaticCacheManager _cacheManager;
        public SystemDataDicService(IRepository<SystemDataDicTree> systemdatadictreeRepo,
            IRepository<SystemDataDicButton> systemdatadicbtnRepository,
            IDomainEventDispatcher eventDispatcher,
            IStaticCacheManager cacheManager)
        {
            this._systemdatadictreeRepository = systemdatadictreeRepo;
            this._systemdatadicbtnRepository = systemdatadicbtnRepository;
            this._eventDispatcher = eventDispatcher;
            this._cacheManager = cacheManager;
        }
        public void DeleteSystemDataDicTree(SystemDataDicTree datadicnode)
        {
            if (datadicnode == null)
                throw new ArgumentNullException(nameof(datadicnode));

            datadicnode.IsActive = EntityEnumConfig.YesorNo.No;
            _systemdatadictreeRepository.Update(datadicnode);

            if (!string.IsNullOrEmpty(datadicnode.SysLogMsg))
                //event notification
                _eventDispatcher.Dispatch(new EntityDeletedEvent<SystemDataDicTree>(datadicnode));
        }

        public IList<SystemDataDicTree> GetSystemDataDicTreesAll()
        {
            var key = DefaultCacheConfig.SystemDataDicTreeAllCacheKey;
            return _cacheManager.Get(key, () =>
            {
                var query = from datadictree in _systemdatadictreeRepository.Table
                            where datadictree.IsActive == EntityEnumConfig.YesorNo.YES
                            orderby datadictree.GroupType, datadictree.DisplayOrder
                            select datadictree;
                var datadicTrees = query.ToList();
                return datadicTrees;
            });
        }
        public IList<SystemDataDicTree> GetDataDicTreeByGroupType(EntityEnumConfig.DataDicGroup groupkey, int? parentId = null)
        {
            var datadicTrees = GetSystemDataDicTreesAll();
            if (datadicTrees.Count > 0 && parentId.HasValue)
                return datadicTrees.Where(d => d.GroupType == groupkey && d.ParentId == parentId.Value).ToList();
            else if (datadicTrees.Count > 0)
                return datadicTrees.Where(d => d.GroupType == groupkey).ToList();
            else return null;
        }

        public SystemDataDicTree GetDataDicTreeById(int datadictreeId)
        {
            if (datadictreeId == 0) return null;
            return _systemdatadictreeRepository.GetById(datadictreeId);
        }

        public IList<SystemDataDicTree> GetSystemDataDicTreeByParentId(int parentId = 0)
        {
            return _systemdatadictreeRepository.Table.Where(d => d.IsActive == EntityEnumConfig.YesorNo.YES && d.ParentId == parentId)
                                               .OrderBy(d => d.GroupType).ThenBy(d => d.DisplayOrder)
                                               .ToList();
        }

        public void InsertSystemDataDicTree(SystemDataDicTree datadicnode)
        {
            if(datadicnode == null) throw new ArgumentNullException(nameof(datadicnode));

            _systemdatadictreeRepository.Insert(datadicnode);

            //event notification
            if (!string.IsNullOrEmpty(datadicnode.SysLogMsg))
                _eventDispatcher.Dispatch(new EntityInsertedEvent<SystemDataDicTree>(datadicnode));
        }

        public void UpdateSystemDataDicTree(SystemDataDicTree datadicnode)
        {
            if (datadicnode == null)
                throw new ArgumentNullException(nameof(datadicnode));

            _systemdatadictreeRepository.Update(datadicnode);

            //event notification
            if (!string.IsNullOrEmpty(datadicnode.SysLogMsg))
                _eventDispatcher.Dispatch(new EntityUpdatedEvent<SystemDataDicTree>(datadicnode));
        }

        public IViewPagedList<SystemDataDicButton> GetSystemDataDicButtons(int fktreeId, int pageIndex = 0, int pageSize = int.MaxValue)
        {
            if (fktreeId <= 0) return null;
            var query = _systemdatadicbtnRepository.Table.Where(n => n.FKSystemDataDicTreeId == fktreeId &&  n.IsActive == EntityEnumConfig.YesorNo.YES)
                                           .OrderBy(n => n.ButtonType).ThenBy(n => n.DisplayOrder);
            var btns = new ViewPagedList<SystemDataDicButton>(query, pageIndex, pageSize);
            return btns;
        }

        public IList<SystemDataDicButton> GetSystemDataDicButtonsByIds(int[] ids)
        {
            if (ids.Length <= 0) return null;
            return _systemdatadicbtnRepository.Table.Where(n => ids.Contains(n.Id)).OrderBy(b => b.DisplayOrder).ToList();
        }

        public IList<SystemDataDicButton> GetSystemDataDicButtonsAll()
        {
            var query = _systemdatadicbtnRepository.Table.Where(n => n.IsActive == EntityEnumConfig.YesorNo.YES)
                                                   .OrderBy(n => n.ButtonType).ThenBy(n => n.DisplayOrder);
            return query.ToList();
        }
    }
}
